/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "weight.h"
#include "util.h"

// QtCore
#include <QString>
#include <QMap>

Weight::Weight(const double iWeight, const WeightUnit iUnit)
{
    _Value = iWeight;
    switch (iUnit)
    {
    case Kilogram:
        _GUIUnit=Kilogram;
        break;
    case Gram:
        _Value*=WCoeffGram;
        _GUIUnit=Gram;
        break;
    case Ounce:
        _Value*=WCoeffOunce;
        _GUIUnit=Ounce;
        break;
    case Pound:
        _Value*=WCoeffPound;
        _GUIUnit=Pound;
        break;
    }
}

Weight::Weight(const Weight &iW)
{
    _Value = iW._Value;
    _GUIUnit = iW._GUIUnit;
}

Weight & Weight::operator=(const Weight &iW)
{
    if (this!=&iW)
    {
        _Value = iW._Value;
        _GUIUnit = iW._GUIUnit;
    }
    return *this;
}

Weight::~Weight()
{
}

bool Weight::operator==(const Weight &iW) const
{
    return ComparePrecision(_Value,iW._Value,0.0001);
}

bool Weight::operator!=(const Weight &iW) const
{
    return (!ComparePrecision(_Value,iW._Value,0.0001));
}

const Weight Weight::operator+(const Weight &iW) const
{
    return Weight(_Value+iW._Value,Kilogram);
}

const Weight Weight::operator-(const Weight &iW) const
{
    return Weight(_Value-iW._Value,Kilogram);
}

bool Weight::operator<(const Weight &iW) const
{
    return (Compare(iW)<0);
}

bool Weight::operator<=(const Weight &iW) const
{
    return (Compare(iW)<=0);
}

bool Weight::operator>(const Weight &iW) const
{
    return (Compare(iW)>0);
}

bool Weight::operator>=(const Weight &iW) const
{
    return (Compare(iW)>=0);
}

double Weight::Value(WeightUnit iUnit) const
{
    double oVal = _Value;
    switch (iUnit)
    {
    case Kilogram:
        break;
    case Gram:
        oVal/=WCoeffGram;
        break;
    case Ounce:
        oVal/=WCoeffOunce;
        break;
    case Pound:
        oVal/=WCoeffPound;
        break;
    }
    return oVal;
}

// Global Weight QMap
static QMap<QString,WeightUnit> WeightUnitMap;
static bool WeightUnitMapInit = false;

void Weight::FromString(const QString &iString, bool *OK)
{
    bool tmpOK = false;

    if (!WeightUnitMapInit)
    {
        WeightUnitMap["kg"] = Kilogram;
        WeightUnitMap["g"]  = Gram;
        WeightUnitMap["oz"] = Ounce;
        WeightUnitMap["lb"] = Pound;
        WeightUnitMapInit = true;
    }

    QString Unit;
    double Val;
    StringToUnit(iString,Val,Unit);

    // Case no Unit
    if (Unit.isEmpty())
    {
        // Just copy value
        _Value = Val;
        _GUIUnit = Kilogram;
        tmpOK = true;
    }
    else
    {
        if (WeightUnitMap.contains(Unit))
        {
            // Build weight with proper unit
            WeightUnit zeUnit = WeightUnitMap[Unit];
            (*this)=Weight(Val,zeUnit);
            tmpOK = true;
        }
    }

    if (0!=OK)
        (*OK)=tmpOK;
}

void Weight::GUIValue(double &oVal, QString &oUnit) const
{
    if (!WeightUnitMapInit)
    {
        WeightUnitMap["kg"] = Kilogram;
        WeightUnitMap["g"]  = Gram;
        WeightUnitMap["oz"] = Ounce;
        WeightUnitMap["lb"] = Pound;
        WeightUnitMapInit = true;
    }

    oVal = _Value;
    switch (_GUIUnit)
    {
    case Kilogram:
        break;
    case Gram:
        oVal/=WCoeffGram;
        break;
    case Ounce:
        oVal/=WCoeffOunce;
        break;
    case Pound:
        oVal/=WCoeffPound;
        break;
    }
    oUnit = WeightUnitMap.key(_GUIUnit);
}

double Weight::Compare(const Weight &iW) const
{
    return (_Value - iW._Value);
}
